import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class MainFrame extends JComponent implements MouseMotionListener,
		MouseListener {

	private static final long serialVersionUID = 1L;

	ClassDiagram initDiagram;
	
	List<Diagram> diagrams;
	List<Link> links;
	
	public static final String CLASS_DIAGRAM_LOCATION = "class_diagram.jpg";
	public static final int DIAGRAM_HEIGHT = 110;
	public static final int DIAGRAM_WIDTH = 130;
	boolean isDiagram = false;
	int diffX, diffY;
	Point eventTriggeredLoc;

	public MainFrame() {
		initComponents();
		addMouseListener(this);
		addMouseMotionListener(this);

	}

	public void initComponents() {
		BufferedImage img = null;
		try {
			img = ImageIO.read(new File(CLASS_DIAGRAM_LOCATION));
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}

		Point initLoc = new Point(0, 0);
		this.initDiagram = new ClassDiagram(initLoc, img, "Init");

		diagrams = new ArrayList<Diagram>();
		links = new ArrayList<Link>();
//		isDrawingLink = false;
		isDiagram = true;
		// label = new JLabel();
		// label.setText("TESTTTTTTTTT");
		// label.setBounds(50, 50, 40, 20);
	}

	public void paint(Graphics g) {
		super.paintComponents(g);

		// deseneaza diagrama initiala
		g.drawImage(initDiagram.getDiagram(),initDiagram.getLocation().x,
				initDiagram.getLocation().y, DIAGRAM_WIDTH, DIAGRAM_HEIGHT, this);

		// deseneaza celelate diagrame
		for (Diagram d : diagrams) {
			g.drawImage(d.getDiagram(), d.getLocation().x, d.getLocation().y, DIAGRAM_WIDTH , DIAGRAM_HEIGHT ,
					null);
		}

		// deseneaza legaturile dintre diagrame
		for (Link link : links) {
			link.drawLink(g);
//			g.drawLine(link.getFrom().x, link.getFrom().y, link.getTo().x,
//					link.getTo().y);
		}
	}

	public static BufferedImage copy(BufferedImage src) {
		BufferedImage copyOfImage = new BufferedImage(src.getWidth(),
				src.getHeight(), BufferedImage.TYPE_INT_RGB);
		Graphics g = copyOfImage.getGraphics();
		g.dispose();
		return copyOfImage;

	}

	public void mouseClicked(MouseEvent me) {

		// verifica daca se apasa pe imaginea initiala
		if (0 <= me.getX() && me.getX() <= initDiagram.getDiagram().getWidth()
				&& 0 <= me.getY()
				&& me.getY() <= initDiagram.getDiagram().getHeight()) {
			Random r = new Random();
			int x = r.nextInt(450);
			int y = r.nextInt(450);
			Point loc = new Point(x, y);
			BufferedImage img = null;
			try {
				img = ImageIO.read(new File(CLASS_DIAGRAM_LOCATION));
			} catch (IOException e) {
				e.printStackTrace();
			}
			Diagram d = new ClassDiagram(loc, img);
			diagrams.add(d);
		}
		repaint();
	}

	@Override
	public void mousePressed(MouseEvent me) {
		if (isMouseOnDiagram(me, this.diagrams)) {
			isDiagram = true;
			this.diffX = me.getX() - this.initDiagram.getDiagram().getWidth();
			this.diffY = me.getY() - this.initDiagram.getDiagram().getHeight();
		} else {
			// isDrawingLink = true;
			isDiagram = false;
			this.eventTriggeredLoc = new Point(me.getX(), me.getY());
		}

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		if (!isDiagram) {
			if(e.getX() == this.eventTriggeredLoc.x && e.getY() == this.eventTriggeredLoc.y){
				return;
			}
			Point to = new Point(e.getX(), e.getY());
			Link link = new Link();
			link.setFrom(this.eventTriggeredLoc);
			link.setTo(to);
			links.add(link);
//			isDrawingLink = true;
			repaint();
		}

	}

	@Override
	public void mouseDragged(MouseEvent me) {
//		isDrawingLink = false;
		for (Diagram d : diagrams) {
			if (isDiagramDragged(d, me)) {
				d.getLocation().setLocation(me.getX() - diffX,
						me.getY() - diffY);
				break;
			}
		}
		if (isDiagram) {
			repaint();
		}

	}

	private boolean isMouseOnDiagram(MouseEvent me, List<Diagram> diagrams) {
		if (diagrams == null) {
			return false;
		}
		for (Diagram d : diagrams) {
			if (isDiagramDragged(d, me)) {
				return true;
			}
		}
		return false;

	}

	private boolean isDiagramDragged(Diagram d, MouseEvent me) {
		if (d.getLocation().x <= me.getX()
				&& me.getX() <= (d.getLocation().x + DIAGRAM_WIDTH)
				&& d.getLocation().y <= me.getY()
				&& me.getY() <= (d.getLocation().y + DIAGRAM_HEIGHT)) {
			return true;
		}
		return false;
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void repaint() {
		super.repaint();
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public static void main(String args[]) {
		JFrame frame = new JFrame("Editor de diagrame");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(1000, 900);
		MainFrame imageDragComponent = new MainFrame();
		frame.getContentPane().add(imageDragComponent);
		frame.setVisible(true);

	}

}
